import imaplib
import email
import dbf
import tempfile
import os
import shutil


# IMAP version 4 is described in RFC1730
class ImapFetch:
    """Downloader de atasamente de email de pe server IMAP4."""

    def __init__(self, host, port=993, use_ssl=True):
        if use_ssl == True:
            self._imap_server = imaplib.IMAP4_SSL(host, port)
        else:
            self._imap_server = imaplib.IMAP4(host, port)

        self.logged_in = False
        self.some_files_could_not_be_read = False

    def _dbf_move_file(self, filename, to_folder, use_fields=None):
        """Redenumeste/Muta fisierul dbf, optional folosind valorile citite din
        fiserul dbf in campurile use_fields, separate de un underscore."""
        table = dbf.Table(filename)
        table.open(mode=dbf.READ_ONLY)
        for record in table:
            try:
                if use_fields:
                    field_names = []
                    for idx in use_fields:
                        field_names.append(record[idx].strip())  # stripping leading and trailing whitespace
                    new_basename = '_'.join(field_names) + '.dbf'
                    new_filename = os.path.join(to_folder, new_basename)
                    table.close()  # close table before we move the file
                    shutil.copy(filename, new_filename)
                    os.remove(filename)
                    print("Mutat/Redenumit: %s --> %s" % (filename, new_filename))
                else:
                    table.close()
                    shutil.copy(filename, to_folder)
                    print("Mutat: %s -> %s" % (filename, to_folder))
                break  # don't advance to next record
            except IOError as e:
                print("Avertizare: nu am putut muta fisierul %s --> %s" %
                    (filename, to_folder))
                print(e)
            except IndexError as e:
                print ("Eroare: Index eronat pentru %s: %s" % (filename, e))

    def login(self, username, password):
        """Incearca sa conecteze la server folosind datele de logare date."""
        if self.logged_in == True:
            self.logout()
        try:
            typ, data = self._imap_server.login(username, password)
            if typ == 'OK':
                self.logged_in = True
        except:
            self.logged_in = False
            raise

    def logout(self):
        """Deconecteaza de la server."""
        try:
            self._imap_server.close()
            self._imap_server.logout()
        except:
            pass
        self.logged_in = False

    def fetch_attachments(self,
        file_extension, to_folder, mailbox='INBOX', move_to=None):
        """Descarca atasamentele cu extensia specificata din folderul specificat.

        Optional se poate specifica un folder IMAP in care vor fi mutate emailurile
        a caror atasamente au fost descarcate.

        Example:
        instance.fetch_attachments('.dbf', '/home/user/folder')
        """
        if not self.logged_in:
            raise Exception("You are not logged in to be able to fetch any attachments!")

        print("Selecting mailbox %s" % mailbox)
        readonly = move_to and False
        typ, data = self._imap_server.select(mailbox=mailbox, readonly=readonly)
        if typ != 'OK':
            raise Exception("Could not select IMAP mailbox %s" % mailbox)

        # Get a list of all emails in INBOX, data contains a list of matching email numbers.
        typ, data = self._imap_server.search(None, 'ALL')

        # Iterate over each message using its order number
        # (might change if a message is deleted or moved while iterating!)
        print("Inspecting emails")
        for num in data[0].split():
            typ2, data2 = self._imap_server.fetch(num, '(RFC822)')
            # Construct email object from string
            e = email.message_from_string(data2[0][1])
            # Read attachments
            for part in e.walk():
                # Check if part has an attachment:
                if (part.get('Content-Disposition') and
                    part.get('Content-Disposition').startswith("attachment")):
                    filename = part.get_filename()
                    # Check if attachment file has the file_extension specified:
                    if ((filename != None) and
                        (os.path.splitext(filename)[1].lower() == file_extension.lower())):
                        # Decoding file content according to it's
                        # Content-Encoding into a str object:
                        buf = part.get_payload(decode=True)
                        # print 'Writing file to temporary directory'
                        f = open(os.path.join(tempfile.gettempdir(), filename), 'wb')
                        f.write(buf)  # write temporary file
                        f.flush()
                        f.close()
                        if file_extension == '.dbf':
                            # use _dbf_move_file to save files using proper names:
                            self._dbf_move_file(f.name, to_folder, (0, 1, 31, 32))
                        else:
                            # otherwise just save it where specified:
                            shutil.copyfile(f.name, to_folder)
                            os.remove(f.name)
        print("Finished fetching attachments")
